package event

const (
	Version          uint8 = 1
	ProtocalSize     uint8 = 32
	MessageBlockSize int   = 1024
	//消息类型
	MessageTypeRegister   uint8 = 1
	MessageTypeUnRegister uint8 = 2
	MessageTypePing       uint8 = 3
	MessageTypePong       uint8 = 4
	MessageTypeEventReg   uint8 = 10
	MessageTypeEvent      uint8 = 11
	MessageTypeComm       uint8 = 100
)

type Message struct {
	ProtocalVersion  uint8
	ProtocalSize     uint8
	ClientId         [4]byte
	MessageBlockSize int
	CutSize          uint8
	CutIndex         uint8
	MessageType      uint8
	MessageId        [8]byte
	MessageIdInt     uint32
	CheckSum         uint8
	Body             []byte
}

func NewMessageFromMessage(message []byte) *Message {
	m := &Message{ProtocalVersion: Version, ProtocalSize: ProtocalSize, MessageBlockSize: 0}
	m.ProtocalVersion = message[0]
	m.ProtocalSize = message[1]
	m.ClientId[0] = message[2]
	m.ClientId[1] = message[3]
	m.ClientId[2] = message[4]
	m.ClientId[3] = message[5]
	m.CutSize = message[6]
	m.CutIndex = message[7]
	m.MessageType = message[8]
	m.MessageIdInt = uint32(message[9]) |
		uint32(message[10])<<8 |
		uint32(message[11])<<16 |
		uint32(message[12])<<24
	for i := 0; i < 4; i++ {
		m.MessageId[i] = message[9+i]
	}
	m.CheckSum = message[31]
	if len(message) > 32 {
		m.Body = message[32:]
	}
	return m
}

func (m *Message) CreateHeader() []byte {
	header := [32]byte{}
	header[0] = m.ProtocalVersion
	header[1] = m.ProtocalSize
	header[2] = m.ClientId[0]
	header[3] = m.ClientId[1]
	header[4] = m.ClientId[2]
	header[5] = m.ClientId[3]

	return header[:]
}

func NewPingMessage(clientId [4]byte) [32]byte {
	data := [32]byte{}
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypePing
	data[31] = createCheck(data[:31])
	return data
}

func NewPongMessage(clientId [4]byte) [32]byte {
	data := [32]byte{}
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypePong
	data[31] = createCheck(data[:31])
	return data
}

func NewRegMessage(clientId [4]byte) [32]byte {
	data := [32]byte{}
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypeRegister
	data[31] = createCheck(data[:31])
	return data
}

func NewUnRegMessage(clientId [4]byte) [32]byte {
	data := [32]byte{}
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypeUnRegister
	data[31] = createCheck(data[:])
	return data
}

func NewEventRegMessage(clientId [4]byte, topic string) []byte {
	data := make([]byte, 32)
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypeEventReg
	data[31] = createCheck(data[:])
	eventMessage := new(EventMessage)
	eventMessage.Topic = topic
	eventMessage.ToBytes()
	data = append(data, eventMessage.ToBytes()...)
	return data
}

func NewEventMessage(clientId [4]byte, body []byte) []byte {
	data := make([]byte, 32)
	data[0] = Version
	data[1] = ProtocalSize
	data[2] = clientId[0]
	data[3] = clientId[1]
	data[4] = clientId[2]
	data[5] = clientId[3]
	data[8] = MessageTypeEvent
	data[31] = createCheck(data[:])
	data = append(data, body...)
	return data
}

func createCheck(header []byte) uint8 {
	var sum int64 = 0
	for i := 0; i < 31; i++ {
		sum += int64(header[i])
		sum = sum % 256
	}
	return uint8(sum)
}

func isValidMessage(message []byte) bool {
	return createCheck(message[:31]) == message[31]
}
